---
layout: docs
page_title: Nomad Access Control List (ACL) policy specification
description: |-
  Learn about Nomad's ACL policy specification. Review namespace, node, node pools, agent, operator, resource quota, host volume, and plugin rules policy structure and options. Configure ACLs for the Nomad UI.
---

# Nomad Access Control List (ACL) policy specification

The [Secure Nomad with Access Control] guide includes step-by-step instructions
for bootstrapping Nomad's Access Control List (ACL) system, authoring policies,
and granting policies. This document is a detailed reference of the expected
policy structure and available options.

ACL policies are written using [HashiCorp Configuration Language
(HCL)][hcl]. The HCL interpreter can also parse JSON to facilitate
machine-generated configuration. A detailed syntax specification for HCL can be
found at [HCL Native Syntax Specification][hcl_syntax_spec].

All content of an ACL policy is case-sensitive.

An ACL policy contains one or more **rules**. Each rule block contains a
combination of `policy` and `capabilities` fields. The specific values permitted
are described for each rule definition below. An example structure of an ACL
policy is as follows:

```hcl
# this is a namespace rule for the "foo" namespace
namespace "foo" {
  policy = "write"                # this is a policy field
  capabilities = ["alloc-exec"]  # this is a capabilities list

  # this block controls access to variables in this namespace
  variables {
    path "project/*" {
      capabilities = ["read", "write"]
    }
  }
}

# this is a namespace rule, with a wildcard label
namespace "*" {
  policy = "read"
}

node {
  policy = "read"
}

agent {
  policy = "read"
}

operator {
  policy = "read"
}

quota {
  policy = "read"
}

# this is a host_volume rule, with a wildcard label
host_volume "*" {
  policy = "read"
}

plugin {
  policy = "read"
}
```

## Namespace rules

Namespace rules are defined with a `namespace` block. An ACL policy can include
zero, one, or more namespace rules.

Namespace rules control access to APIs in Nomad that are namespaced:
[Jobs][api_jobs], [Allocations][api_allocations],
[Deployments][api_deployments], [Evaluations][api_evaluations],
[Recommendations][api_recommendations], [Scaling
Policies][api_scaling_policies], [Services][api_services], and
[Volumes][api_volumes]. Namespace rules also filter items related to the above
APIs from the [Event Stream][api_events] and [Search][api_search] APIs.

Each namespace rule is labeled with the namespace name it applies to. If no
namespace label is specified, the rule will apply to the "default"
namespace. You may use wildcard globs (`"*"`) in the namespace label, to apply a
rule to multiple namespaces.

Only one namespace rule can apply. When Nomad checks an action against the ACL
Policy, the namespace rule is selected by first checking for an _exact match_,
before falling back to a glob-based lookup. When looking up the namespace by
glob, Nomad chooses the rule with the greatest number of matched characters. In
other words, Nomad chooses the rule with the _smallest character difference_,
which is the _greatest number of matched characters_.

In this example, you have a 'production-web' namespace. For the `"*-web"` rule,
nine characters match. The character difference is four. For the `"*"`rule, no
characters match the rule. The character difference is thirteen. Nomad chooses
the `"*-web"` rule since it has the greatest number of matched characters.

```hcl
namespace "*-web" {
  policy = "deny"
}

namespace "*" {
  policy = "write"
}
```

Each namespace rule can include a coarse-grained `policy` field, a fine-grained
`capabilities` field, a `variables` block, or all three.

The `policy` field for namespace rules can have one of the following values:
- `read`: allow the resource to be read but not modified
- `write`: allow the resource to be read and modified
- `deny`: do not allow the resource to be read or modified. Deny takes
  precedence when multiple policies are associated with a token.

In addition to the coarse-grained `policy`, you can provide a fine-grained list
of `capabilities`. This includes:

- `deny` - When multiple policies are associated with a token, deny will take
  precedence and prevent any capabilities.
- `list-jobs` - Allows listing the jobs and seeing coarse grain status. This
  implicitly grants `csi-list-volume`.
- `parse-job` - Allows parsing a job from HCL to JSON.
- `read-job` - Allows inspecting a job and seeing fine grain status. This
  implicitly grants `csi-read-volume`.
- `submit-job` - Allows jobs to be submitted, updated, or stopped.
- `dispatch-job` - Allows jobs to be dispatched
- `read-logs` - Allows the logs associated with a job to be viewed.
- `read-fs` - Allows the filesystem of allocations associated to be
  viewed. Implicitly grants `read-logs`.
- `alloc-exec` - Allows an operator to connect and run commands in running
  allocations.
- `alloc-node-exec` - Allows an operator to connect and run commands in
  allocations running without filesystem isolation, for example, raw_exec jobs.
- `alloc-lifecycle` - Allows an operator to stop individual allocations
  manually.
- `csi-register-plugin` - Allows jobs to be submitted that register themselves
  as CSI plugins.
- `csi-write-volume` - Allows CSI volumes to be registered or deregistered. This
  implicitly grants `csi-read-volume`.
- `csi-read-volume` - Allows inspecting a CSI volume, seeing fine grain status,
  and listing external volumes and snapshots. This implicitly grants
  `csi-list-volume`.
- `csi-list-volume` - Allows listing CSI volumes, seeing coarse grain status,
  and listing external volumes and snapshots.
- `csi-mount-volume` - Allows jobs to be submitted that claim a CSI volume. This
  implicitly grants `csi-read-volume`.
- `host-volume-create` - Allows creating dynamic host volumes. This implicitly grants `host-volume-read`.
- `host-volume-delete` - Allows deleting dynamic host volumes.
- `host-volume-read` - Allows inspecting dynamic host volumes.
- `host-volume-register` - Allows registering dynamic host volumes that have been created without a plugin. This implicitly grants `host-volume-read` and `host-volume-create`.
- `host-volume-write` - Allows all write operations on dynamic host volumes. This implicitly grants `host-volume-read`, `host-volume-create`, `host-volume-register`, and `host-volume-delete`.
- `list-scaling-policies` - Allows listing scaling policies.
- `read-scaling-policy` - Allows inspecting a scaling policy.
- `read-job-scaling` - Allows inspecting the current scaling of a job.
- `scale-job`: Allows scaling a job up or down.
- `sentinel-override` - Allows soft mandatory policies to be overridden.
- `submit-recommendation` - Allows submitting vertical job scaling recommendations.

The coarse-grained policy permissions are shorthand for these fine-grained namespace capabilities.



| Policy  | Capabilities                                                                                                                                                                                                                                                                                              |
|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `deny`  | deny                                                                                                                                                                                                                                                                                                      |
| `read`  | list-jobs<br />parse-job<br />read-job<br />csi-list-volume<br />csi-read-volume<br />host-volume-read<br />list-scaling-policies<br />read-scaling-policy<br />read-job-scaling                                                                                                                                                |
| `write` | list-jobs<br />parse-job<br />read-job<br />submit-job<br />dispatch-job<br />read-logs<br />read-fs<br />alloc-exec<br />alloc-lifecycle<br />csi-write-volume<br />csi-mount-volume<br />host-volume-write<br />list-scaling-policies<br />read-scaling-policy<br />read-job-scaling<br />scale-job<br />submit-recommendation |
| `scale` | list-scaling-policies<br />read-scaling-policy<br />read-job-scaling<br />scale-job                                                                                                                                                                                                                       |



If you provide both a `policy` and `capabilities` list, the capabilities are
merged. For example, the policy below adds the `submit-job` capability to the `read`
policy disposition, which provides the `list-job` and `read-job` capabilities:

```hcl
# Allow reading jobs and submitting jobs, without allowing access
# to view log output or inspect the filesystem
namespace "default" {
  policy       = "read"
  capabilities = ["submit-job"]
}
```

A similar policy could also be expressed as:

```hcl
# Allow reading jobs and submitting jobs, without allowing access
# to view log output or inspect the filesystem
namespace "default" {
  capabilities = ["submit-job","list-jobs","read-job"]
}
```

### Variables

The `variables` block in the `namespace` rule controls access to
[Variables][]. The variables block is optional, but you can specify only one
variables block per namespace rule.

A `variables` block includes one or more `path` blocks. Each `path` block is
labeled with the path it applies to. You may use wildcard globs (`"*"`) in the
path label, to apply the block to multiple paths in the namespace. Note that
variable paths never start with a leading `/`, so Nomad will return an error if
you submit a policy that has such a path.

Each path has a list of `capabilities`. The available capabilities for Variables
are as follows:

| Capability | Notes                                                                                                                 |
|------------|-----------------------------------------------------------------------------------------------------------------------|
| write      | Create or update Variables at this path. Includes the "list" capability but not the "read" or "destroy" capabilities. |
| read       | Read the decrypted contents of Variables at this path. Also includes the "list" capability                            |
| list       | List the metadata but not contents of Variables at this path.                                                         |
| destroy    | Delete Variables at this path.                                                                                        |
| deny       | No permissions at this path. Deny takes precedence over other capabilities.                                           |

For example, the policy below allows full access to variables at all paths in
the "dev" namespace that are prefixed with "project/", but only read access to
paths prefixed with "system/". Note that the glob can match an empty string but
all other characters are strictly matched. This policy grants read access to
paths prefixed with "system/" but not a path named "system" (without a trailing
slash). This policy does not grant any other coarse-grained policy or
fine-grained capabilities.

```hcl
namespace "dev" {

  variables {

    # full access to secrets in all "project" paths
    path "project/*" {
      capabilities = ["write", "read", "destroy", "list"]
    }

    # read/list access within a "system/" path belonging to administrators
    path "system/*" {
      capabilities = ["read"]
    }
  }
}
```

## Node rules

The `node` rule controls access to the [Node API][api_node] such as listing
nodes or triggering a node drain. The node rule is optional, but you can specify
only one node rule per ACL Policy.

```hcl
node {
  policy = "read"
}
```

The `policy` field for the node rule can have one of the following values:
- `read`: allow the resource to be read but not modified
- `write`: allow the resource to be read and modified
- `deny`: do not allow the resource to be read or modified. Deny takes
  precedence when multiple policies are associated with a token.

## Node pools rules

Node pool rules are defined with a `node_pool` block. An ACL policy can
include zero, one, or more node pool rules.

Node pool rule controls access to the [Node Pools API][api_node_pool] such as
create, update, and list node pools.

Each node pool rule is labeled with the node pool name it applies to. You may
use wildcard globs (`"*"`) in the label to apply a rule to multiple node pools.

Similarly to [namespace rules](#namespace-rules) only one `node_pool` rule can
be applied. First an _exact match_ is tried before falling back to a glob-based
lookup, where the rule with the greatest number of matched characters is
chosen.

Each node pool rule can include a coarse-grained `policy` field and a
fine-grained `capabilities` field.

The `policy` field for node pool rules can have one of the following values.

- `read` allows node pools to be listed and read but not modified.
- `write` allows node pools to be read, create, updated, and deleted.
- `deny` forbids node pools to be read or modified. Deny takes precedence when
  multiple policies are associated with a token.

In addition to the coarse-grained `policy`, you can provide a fine-grained list
of `capabilities`.

- `deny` forbids node pools to be read or modified. Deny takes precedence when
  multiple policies are associated with a token.
- `delete` allows node pools to be deleted.
- `read` allows node pools to be listed and read.
- `write` allows node pools to be created and updated.

The coarse-grained policy permissions are shorthand for the following
fine-grained capabilities.

| Policy  | Capabilities              |
| ------- | ------------------------- |
| `deny`  | `deny`                    |
| `read`  | `read`                    |
| `write` | `delete`, `read`, `write` |

If you provide both a `policy` and `capabilities` list the capabilities are
merged. For example, the policy below adds the `write` capability to the `read`
policy, thus allowing `read` and `write` permission but no `delete`.

```hcl
node_pool "dev-*" {
  policy       = "read"
  capabilities = ["write"]
}
```

## Agent rules

The `agent` rule controls access to the [Agent API][api_agent] such as join and
leave. The agent rule is optional, but you can specify only one agent rule per
ACL Policy.

```hcl
agent {
  policy = "read"
}
```

The `policy` field for the agent rule can have one of the following values:
- `read`: allow the resource to be read but not modified
- `write`: allow the resource to be read and modified
- `deny`: do not allow the resource to be read or modified. Deny takes
  precedence when multiple policies are associated with a token.

## Operator rules

The `operator` rule controls access to the [Operator API][api_operator] such
raft or scheduler configuration. The operator rule is optional, but you can
specify only one operator rule per ACL Policy.

```hcl
operator {
  policy = "read"
}
```

The `policy` field for the operator rule can have one of the following values:
- `read`: allow the resource to be read but not modified
- `write`: allow the resource to be read and modified
- `deny`: do not allow the resource to be read or modified. Deny takes
  precedence when multiple policies are associated with a token.

In the example above, the token could be used to query the operator endpoints
for diagnostic purposes but not make any changes.

## Quota rules

The `quota` rule controls access to the [Quota API][api_quota] such as quota
creation and deletion. The quota rule is optional, but you can specify only one
quota rule per ACL Policy.

```hcl
quota {
  policy = "read"
}
```

The `policy` field for the quota rule can have one of the following values:
- `read`: allow the resource to be read but not modified
- `write`: allow the resource to be read and modified
- `deny`: do not allow the resource to be read or modified. Deny takes
  precedence when multiple policies are associated with a token.

## Host volume rules

The `host_volume` rule controls access to mounting and accessing [host
volumes][host_volumes]. An ACL Policy can include zero, one, or more host volume
rules.

```hcl
host_volume "*" {
  policy = "write"
}

host_volume "prod-*" {
  policy = "deny"
}

host_volume "prod-ca-certificates" {
  policy = "read"
}
```

Host volume rules are labeled with the volume names that they apply to. As with
namespaces, you may use wildcards to reuse the same configuration across a set
of volumes.

The `policy` field for host volume rules can have one of the following values:
- `read`: allow the resource to be read but not modified
- `write`: allow the resource to be read and modified
- `deny`: do not allow the resource to be read or modified. Deny takes
  precedence when multiple policies are associated with a token.

In addition to the coarse grained policy, host volume rules can include a list
of fine-grained `capabilities`. These include:

- `deny` - Do not allow a user to mount a volume in any way.
- `mount-readonly` - Only allow the user to mount the volume as `readonly`
- `mount-readwrite` - Allow the user to mount the volume as `readonly` or
  `readwrite` if the `host_volume` configuration allows it.

The coarse-grained policy permissions are shorthand for the fine grained
capabilities:



| Policy  | Capabilities                        |
|---------|-------------------------------------|
| `deny`  | deny                                |
| `read`  | mount-readonly                      |
| `write` | mount-readonly<br />mount-readwrite |



When both the policy short hand and a capabilities list are provided, the
capabilities are merged.

~> **Note:** Host Volume policies are applied when attempting to _use_ a volume.
Regardless of this configuration, users with access to the Node API will be able
to list available volumes using the `nomad node status` command or API call. .

## Plugin rules

The `plugin` rule controls access to [CSI plugins][api_plugins], such as listing
plugins or getting plugin status. The plugin rule is optional, but you can
specify only one plugin rule per ACL policy.

```hcl
plugin {
  policy = "read"
}
```

The `policy` field for the plugin rule can have one of the following values:
- `read`: allow the resource to be read but not modified
- `list`: allow the resource to be listed, but not inspected in detail
- `write`: allow the resource to be read and modified
- `deny`: do not allow the resource to be read or modified. Deny takes
  precedence when multiple policies are associated with a token.

## Configure ACLs for the web UI

The Nomad web UI uses the API endpoints `/v1/agent` and `/v1/node` for nearly
every page. ACL policies for users who will use the Nomad UI should include the
following rules.

```hcl
node {
  policy = "read"
}

agent {
  policy = "read"
}
```

Additionally, ACL policies for users who can read jobs that mount CSI volumes
should include the following rules.

```hcl
plugin {
  policy = "read"
}
```

[Secure Nomad with Access Control]: /nomad/tutorials/access-control
[hcl]: https://github.com/hashicorp/hcl
[hcl_syntax_spec]: https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md
[api_jobs]: /nomad/api-docs/jobs
[api_allocations]: /nomad/api-docs/allocations
[api_deployments]: /nomad/api-docs/deployments
[api_evaluations]: /nomad/api-docs/evaluations
[api_recommendations]: /nomad/api-docs/recommendations
[api_scaling_policies]: /nomad/api-docs/scaling-policies
[api_services]: /nomad/api-docs/services
[api_volumes]: /nomad/api-docs/volumes
[api_events]: /nomad/api-docs/events
[api_search]: /nomad/api-docs/search
[api_agent]: /nomad/api-docs/agent/
[api_node]: /nomad/api-docs/nodes/
[api_node_pool]: /nomad/api-docs/node-pools/
[api_operator]: /nomad/api-docs/operator/
[api_quota]: /nomad/api-docs/quotas/
[host_volumes]: /nomad/docs/configuration/client#host_volume-block
[api_plugins]: /nomad/api-docs/plugins/
[Variables]: /nomad/docs/concepts/variables
[federated]: //nomad/docs/deploy/clusters/federate-regions
[`authoritative_region`]: /nomad/docs/configuration/server#authoritative_region
